package org.KeyCrafter.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.redis.*;
import org.KeyCrafter.obj.KeyCrafterObject;
import org.KeyCrafter.obj.StringObj;
import org.KeyCrafter.server.session.ClientSession;

import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

public class ReplyUtil {
    public static void addReply(ClientSession c, RedisMessage reply) {
        c.setReplyMessage(reply);
    }

    public static void addReply(ClientSession c, String reply) {
        addReplyBulk(c, reply);
    }

    public static void addReplySimpleString(ClientSession c, String reply) {
        addReply(c, new SimpleStringRedisMessage(reply));
    }

    public static void addReplyBulk(ClientSession c, KeyCrafterObject reply) {
        if (reply instanceof StringObj) {
            addReplyBulk(c, ((StringObj) reply).getValue().getString());
        }
    }

    public static void addReplyBulk(ClientSession c, String reply) {
        ByteBuf buffer = c.getReplyBuffer();
        if (buffer != null && buffer.refCnt() > 0) {
            // 清空之前的缓存
            c.clearReply();
        } else {
            // 如果使用池化的，申请 ByteBuffer 是否也不会太费时间？
            // client 创建是申请的 byteBuffer 太容易被自动释放掉了
            if (c.channel() == null) {
                // 伪客户端
                return;
            }
            buffer = c.channel().alloc().buffer();
        }
        buffer.writeBytes(reply.getBytes(StandardCharsets.UTF_8));
        c.setReplyMessage(new FullBulkStringRedisMessage(buffer));
    }


    public static void addReplyError(ClientSession c, String err) {
        c.setReplyMessage(new ErrorRedisMessage(err));
    }

    public static void addReplyLong(ClientSession c, long l) {
        // 先从缓存中找
        IntegerRedisMessage message = SharedReply.messagePool.getInteger(l);
        if (message == null) {
            message = new IntegerRedisMessage(l);
        }
        c.setReplyMessage(message);
    }

    public static void addReplyArray(ClientSession c, List<String> list) {
        List<RedisMessage> children = new LinkedList<>();
        for (String s : list) {
            if (s == null) {
                // 空值
                children.add(SharedReply.nullBulk);
            } else {
                ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
                buffer.writeBytes(s.getBytes(StandardCharsets.UTF_8));
                children.add(new FullBulkStringRedisMessage(buffer));
            }
        }
        ArrayRedisMessage message = new ArrayRedisMessage(children);
        c.setReplyMessage(message);
    }

    public static void addReplyArray(ClientSession c, String[] reply) {
        List<RedisMessage> children = new LinkedList<>();
        for (String s : reply) {
            if (s == null) {
                // 空值
                children.add(SharedReply.nullBulk);
            } else {
                ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
                buffer.writeBytes(s.getBytes(StandardCharsets.UTF_8));
                children.add(new FullBulkStringRedisMessage(buffer));
            }
        }
        ArrayRedisMessage message = new ArrayRedisMessage(children);
        c.setReplyMessage(message);
    }

    /*
     * 以 bulk 回复的形式，返回一个双精度浮点数
     *
     * 例子 $4\r\n3.14\r\n
     */
    public static void addReplyDouble(ClientSession c, double d) {
        addReply(c, String.valueOf(d));
    }

    /*
     * 检查对象 o 的类型是否和 type 相同：
     *  1. 相同返回 true
     *  2. 不相同返回 false ，并向客户端回复一个错误
     */
    public static boolean checkType(ClientSession c, KeyCrafterObject obj, byte type) {
        if (obj.getType() != type) {
            addReply(c, SharedReply.wrongTypeErr);
            return false;
        }
        return true;
    }

    private ReplyUtil() {
    }
}
